<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE
The complete set of authors may be found at http://polymer.github.io/AUTHORS
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS
-->
<html>
<head>
  <meta charset="UTF-8">
  <title>iron-list test</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

  <script src="../../webcomponentsjs/webcomponents-lite.js"></script>

  <script src="../../web-component-tester/browser.js"></script>
  <script src="../../test-fixture/test-fixture-mocha.js"></script>
  <script src="../../iron-test-helpers/mock-interactions.js"></script>

  <link rel="import" href="fixtures/helpers.html">
  <link rel="import" href="fixtures/x-list.html">

</head>
<body>

  <test-fixture id="trivialList">
    <template>
      <x-list item-height="10"></x-list>
    </template>
  </test-fixture>

  <script>
    'use strict';
    suite('selection', function() {
      var list, container;

      setup(function() {
        container = fixture('trivialList');
        list = container.list;
      });

      test('single selection by item index', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        assert.isNull(list.selectedItem);
        list.selectIndex(0);
        assert.deepEqual(list.selectedItem, list.items[0]);
        list.deselectIndex(0);
        assert.deepEqual(list.selectedItem, null);
        list.selectIndex(99);
        assert.deepEqual(list.selectedItem, list.items[99]);
      });

      test('single selection by item object', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        assert.isNull(list.selectedItem);
        list.selectItem(list.items[50]);
        assert.deepEqual(list.selectedItem, list.items[50]);
      });

      test('multi selection by item index', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.multiSelection = true;
        assert.isArray(list.selectedItems);
        list.selectIndex(0);
        list.selectIndex(50);
        list.selectIndex(99);
        assert.equal(list.selectedItems.length, 3);
        assert.notEqual(list.selectedItems.indexOf(list.items[0]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[50]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[99]), -1);
        assert.equal(list.selectedItems.indexOf(list.items[2]), -1);
      });

      test('multi selection by item object', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.multiSelection = true;
        assert.isArray(list.selectedItems);
        list.selectItem(list.items[0]);
        list.selectItem(list.items[50]);
        list.selectItem(list.items[99]);
        assert.equal(list.selectedItems.length, 3);
        assert.notEqual(list.selectedItems.indexOf(list.items[0]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[50]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[99]), -1);
        assert.equal(list.selectedItems.indexOf(list.items[2]), -1);
      });

      test('clear selection', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.multiSelection = true;
        assert.isArray(list.selectedItems);
        list.items.forEach(function(item) {
          list.selectItem(item);
        });
        assert.equal(list.selectedItems.length, list.items.length);
        assert.isTrue(list._physicalItems[0].hasAttribute('selected'));
        list.clearSelection();
        assert.equal(list.selectedItems.length, 0);
        assert.isFalse(list._physicalItems[0].hasAttribute('selected'));
      });


      test('toggle selection by item index', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.toggleSelectionForIndex(0);
        assert.deepEqual(list.selectedItem, list.items[0]);
        list.toggleSelectionForIndex(0);
        assert.isNull(list.selectedItem);
      });

      test('toggle selection by item object', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.toggleSelectionForItem(list.items[0]);
        assert.deepEqual(list.selectedItem, list.items[0]);
        list.toggleSelectionForItem(list.items[0]);
        assert.isNull(list.selectedItem);
      });

      test('change multi property', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.multiSelection = true;
        assert.isArray(list.selectedItems);
        list.multiSelection = false;
        assert.isNotArray(list.selectedItems);
        assert.isNull(list.selectedItems);
        list.multiSelection = true;
        assert.isArray(list.selectedItems);
      });

      test('selectionEnabled with single selection', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.selectionEnabled = true;
        assert.isNull(list.selectedItem);
        // select item[0]
        MockInteractions.tap(list._physicalItems[0]);
        assert.deepEqual(list.selectedItem, list.items[0]);
        // select item[5] and deselect item[0]
        MockInteractions.tap(list._physicalItems[5]);
        // select item[1] and deselect item[5]
        MockInteractions.tap(list._physicalItems[1]);
        assert.deepEqual(list.selectedItem, list.items[1]);
      });

      test('selectionEnabled with multiple selection', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        list.multiSelection = true;
        MockInteractions.tap(list._physicalItems[0]);
        assert.equal(list.selectedItems.length, 0);
        // enable the feature
        list.selectionEnabled = true;
        // select item[0]
        MockInteractions.tap(list._physicalItems[0]);
        assert.notEqual(list.selectedItems.indexOf(list.items[0]), -1);
        // multiple selection
        MockInteractions.tap(list._physicalItems[1]);
        MockInteractions.tap(list._physicalItems[5]);
        MockInteractions.tap(list._physicalItems[10]);
        MockInteractions.tap(list._physicalItems[12]);

        list.selectIndex(0);
        list.deselectIndex(1);

        assert.equal(list.selectedItems.indexOf(list.items[1]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[0]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[5]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[10]), -1);
        assert.notEqual(list.selectedItems.indexOf(list.items[12]), -1);

        list.clearSelection();

        assert.equal(list.selectedItems.length, 0);
        // disable the feature
        list.selectionEnabled = false;
        MockInteractions.tap(list._physicalItems[1]);

        assert.equal(list.selectedItems.length, 0);

        list._physicalItems[1].focus();
        MockInteractions.keyDownOn(list._physicalItems[1], 13 /* ENTER */);

        assert.equal(list.selectedItems.length, 0);
      });

    test('toggle', function() {
      list.items = buildDataSet(100);
      PolymerFlush();
      list.selectionEnabled = true;
      MockInteractions.tap(list._physicalItems[0]);
      assert.deepEqual(list.selectedItem, list.items[0]);
      MockInteractions.tap(list._physicalItems[0]);
      assert.isNull(list.selectedItem);
      MockInteractions.tap(list._physicalItems[0]);
      list.clearSelection();
      assert.isNull(list.selectedItem);
    });

     test('selectedAs', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
          // Multi selection.
        list.multiSelection = true;
        assert.isFalse(list.modelForElement(list._physicalItems[0]).selected);
        list.selectIndex(0);
        assert.isTrue(list.modelForElement(list._physicalItems[0]).selected);
        list.toggleSelectionForIndex(0);
        assert.isFalse(list.modelForElement(list._physicalItems[0]).selected);
        // Single selection.
        list.multiSelection = false;
        list.selectIndex(0);
        list.selectIndex(10);
        assert.isFalse(list.modelForElement(list._physicalItems[0]).selected);
        assert.isTrue(list.modelForElement(list._physicalItems[10]).selected);
      });

      test('splice a selected item', function() {
        list.items = buildDataSet(100);
        PolymerFlush();
        // Multi selection.
        list.multiSelection = true;
        // select the first two items
        list.selectIndex(0);
        list.selectIndex(1);
        assert.equal(list.selectedItems.length, 2);
        // Remove the first two items.
        list.splice('items', 0, 2);
        assert.equal(list.selectedItems.length, 0);
      });

      test('single selection of a primitive type', function() {
        list.primitive = true;
        list.items = ['a', 'b', 'c', 'd'];
        list.selectionEnabled = true;
        PolymerFlush();
        list.selectIndex(0);
        assert.equal(list.selectedItem, 'a', 'single selection 1');
        list.clearSelection();
        assert.isNull(list.selectedItem);
        list.selectIndex(2);
        list.set('items.0', 'z');
        list.set('items.1', 'y');
        assert.equal(list.selectedItem, 'c', 'single selection 2');
      });

      test('multi selection of a primitive types', function() {
        list.primitive = true;
        list.items = ['a', 'b', 'c', 'd'];
        list.selectionEnabled = true;
        list.multiSelection = true;
        PolymerFlush();
        list.selectIndex(0);
        list.selectIndex(1);
        assert.deepEqual(list.selectedItems, ['a', 'b'], 'multiple selection 1');
        list.clearSelection();
        assert.equal(list.selectedItems.length, 0, 'multiple selection 2');
      });

      // This is no longer supported.
      // Mutating the item value will deselect that item.
      // test('modify primitive item while being selected', function() {
      //   list.primitive = true;
      //   list.items = ['a', 'b', 'c', 'd'];
      //   list.selectionEnabled = true;
      //   PolymerFlush();
      //   list.selectIndex(0);
      //   list.items[0] = 'z';
      //   list.items = list.items;
      //   list.set('items.0', 'z');
      //   assert.equal(list.selectedItem, 'z', 'single selection 1');
      //   list.selectIndex(2);
      //   assert.equal(list.selectedItem, 'c', 'single selection 2');
      //   list.clearSelection();
      //   assert.isNull(list.selectedItem);
      //   // test multi selection
      //   list.multiSelection = true;
      //   list.selectIndex(0);
      //   list.selectIndex(1);
      //   assert.deepEqual(list.selectedItems, ['z', 'b'], 'multiple selection 1');
      //   list.set('items.1', 'y');
      //   assert.deepEqual(list.selectedItems, ['z', 'y'], 'multiple selection 2');
      //   list.deselectItem('y');
      //   assert.deepEqual(list.selectedItems, ['z'], 'multiple selection 3');
      //   list.deselectItem('z');
      //   assert.equal(list.selectedItems.length, 0);
      // });

      test('tapping on a focusable child should not change the selection', function() {
        list.items = buildDataSet(1);
        list.selectionEnabled = true;
        PolymerFlush();
        var node = document.createElement('div');
        node.innerText = 'focusable';
        node.tabIndex = 0;
        Polymer.dom(getFirstItemFromList(list)).appendChild(node);
        PolymerFlush();
        node.focus();
        MockInteractions.tap(node);
        assert.isNull(list.selectedItem);
      });

      test('try to select active element', function() {
        container.useTabIndex = false;
        list.items = buildDataSet(1);
        list.selectionEnabled = true;
        PolymerFlush();
        var item = list._physicalItems[0];
        item.focus();
        MockInteractions.tap(item);
        assert.isNotNull(list.selectedItem);
      });
    });

  </script>

</body>
</html>
